 //Draw curve passing through the give points with specified tension
	function drawCurve(pen,points,tension,isClosed) 
	{
		if(!pen || !points)
			return false;
			
		if(!tension)
		{
			tension=0;
		}
		if(!isClosed)
		{
			isClosed=false;
		}

		var phPoints=new Array();
		for(var i=0;i<points.length;i++)
		{
			phPoints[i]=logicalToPhysicalPoint(points[i]);
		}
		
		var newPoints=new Array();

   		//Remove duplicate consecutive points (ToDo: neccessity of this step is to be confirmed)		
        if(!isClosed || !(phPoints[0].x==phPoints[phPoints.length-1].x && phPoints[0].y==phPoints[phPoints.length-1].y))
        {
            newPoints[newPoints.length]=phPoints[0];  
        }  

		for(var i=1;i<phPoints.length;i++)
		{
		    if(!(phPoints[i].x==phPoints[i-1].x && phPoints[i].y==phPoints[i-1].y))
		    {
		        newPoints[newPoints.length]=phPoints[i];  
		    }   
		}
        phPoints=newPoints;
        
        if(phPoints.length<2)
		{
			return false;
		}
		else if(phPoints.length==2)
		{
		    //For 2 points just draw a line connecting them.
			return this.drawLine(pen,phPoints[0],phPoints[1],"physical");
		}

	    var curveDiv=canvasDiv.appendChild(document.createElement("div"));
        var iHtml=new Array();
        //Array to hold points on the curve
		var curvePoints=new Array();
		
		var n=phPoints.length-1;
		//Call drawCurveSeg method in loop to get points in curvePoints 
		//array for segment (connecting 2 points) of the curve. 
		if(!isClosed) //for open curve
		{	
			for(var i=0;i<=n-1;i++)
			{
				if(i==0)
				{
					drawCurveSeg(new Array(phPoints[0],phPoints[0],phPoints[1],phPoints[2]),tension,curvePoints);
				}
				else if(i==n-1)
				{
					drawCurveSeg(new Array(phPoints[n-2],phPoints[n-1],phPoints[n],phPoints[n]),tension,curvePoints);
				}
				else
				{
					drawCurveSeg(new Array(phPoints[i-1],phPoints[i],phPoints[i+1],phPoints[i+2]),tension,curvePoints);
				}
			}
			//Actual drawing using points data in curvePoints array
			drawAllCurvePoints(pen,curvePoints,iHtml);
		}
		else //for closed curve
		{
			for(var i=0;i<=n-1;i++)
			{
				if(i==0)
				{
					drawCurveSeg(new Array(phPoints[n],phPoints[0],phPoints[1],phPoints[2]),tension,curvePoints);
				}
				else if(i==n-1)
				{
					drawCurveSeg(new Array(phPoints[n-2],phPoints[n-1],phPoints[n],phPoints[0]),tension,curvePoints);
				}
				else
				{
					drawCurveSeg(new Array(phPoints[i-1],phPoints[i],phPoints[i+1],phPoints[i+2]),tension,curvePoints);
				}
			}
			drawCurveSeg(new Array(phPoints[n-1],phPoints[n],phPoints[0],phPoints[1]),tension,curvePoints);
			//Actual drawing using points data in curvePoints array
			drawAllCurvePoints(pen,curvePoints,iHtml);
		}
		        
		curveDiv.innerHTML=iHtml.join("");
		return curveDiv;
	}




    //Private function used by drawCurve method to get curve points 
    //(in curvePoints array) for a single curve segment (connecting 2 points)
	function drawCurveSeg(segPoints,tension,curvePoints)
	{
		var x=0;
		var y=0;
		var xl=segPoints[1].x-1;
		var yl=segPoints[1].y-1;

		var	t=0;
		var f=1;
		var k=1.1;

		var m1x=(1-tension)*(segPoints[2].x-segPoints[0].x)/2;
		var m2x=(1-tension)*(segPoints[3].x-segPoints[1].x)/2;

		var m1y=(1-tension)*(segPoints[2].y-segPoints[0].y)/2;
		var m2y=(1-tension)*(segPoints[3].y-segPoints[1].y)/2;
		
		while(t<=1)
		{
			x=0;
			y=0;

			x= (2*t*t*t-3*t*t+1)*segPoints[1].x + (t*t*t-2*t*t+t)*m1x + (-2*t*t*t+3*t*t)*segPoints[2].x + (t*t*t-t*t)*m2x;
			y= (2*t*t*t-3*t*t+1)*segPoints[1].y + (t*t*t-2*t*t+t)*m1y + (-2*t*t*t+3*t*t)*segPoints[2].y + (t*t*t-t*t)*m2y;
				
			x=Math.round(x);
			y=Math.round(y);

			if(x!=xl || y!=yl)
			{
				if(x-xl>1 || y-yl>1 || xl-x>1 || yl-y>1)
				{
					t-=f;
					f=f/k;
				}
				else
				{
	                curvePoints[curvePoints.length]=new jsPoint(x,y); 
					xl=x;
					yl=y;
	                if(t+f>1)
	                    t=1-f;
				}
			}
			else
			{
				f=f*k;
			}
			t+=f;
		}
	}





















//Draw Line between the 2 specified points based on Mid point Algorithm.
	function drawLine(pen,point0,point1)
	{
		//Check arguments for null values
		if(!pen || !point0 || !point1)
			return false;
			
	    var lineDiv=canvasDiv.appendChild(document.createElement("div"));
	    
	    //Some library functions use drawLine method and need to pass physical points only. So the following check.
	    if(arguments[3]!="physical") 
	    {
	    	phPoint0=logicalToPhysicalPoint(point0);
	   	    phPoint1=logicalToPhysicalPoint(point1);
   	    }
   	    else
   	    {
   	    	phPoint0=new jsPoint(point0.x,point0.y);
   	    	phPoint1=new jsPoint(point1.x,point1.y);
   	    }

	 	var x0, x1, y0, y1;
	 	x0=phPoint0.x;
	 	x1=phPoint1.x;
	 	y0=phPoint0.y;
	 	y1=phPoint1.y;
	 	
	 	var hexColor=pen.color.getHex();
   	 	//For Horizontal line
	 	if(y0==y1)
	 	{
	 		if(x0<=x1)
		 		lineDiv.innerHTML="<DIV style=\"position:absolute;overflow:hidden;left:" + x0 + "px;top:" + y0 + "px;width:" + (x1-x0+1) + "px;height:" + pen.width + 

";background-color:" + hexColor + "\"></DIV>";
	 		else if(x0>x1)
		 		lineDiv.innerHTML="<DIV style=\"position:absolute;overflow:hidden;left:" + x1 + "px;top:" + y0 + "px;width:" + (x0-x1+1) + "px;height:" + pen.width + 

";background-color:" + hexColor + "\"></DIV>";
		 		
	 		return lineDiv;
	 	}
	 	
	 	//For Vertical line
	 	if(x0==x1)
	 	{
	 		if(y0<=y1)
		 		lineDiv.innerHTML="<DIV style=\"position:absolute;overflow:hidden;left:" + x0 + "px;top:" + y0 + "px;width:" + pen.width + ";height:" + (y1-y0+1) + 

"px;background-color:" + hexColor + "\"></DIV>";
	 		else if(y0>y1)
		 		lineDiv.innerHTML="<DIV style=\"position:absolute;overflow:hidden;left:" + x0 + "px;top:" + y1 + "px;width:" + pen.width + ";height:" + (y0-y1+1) + 

"px;background-color:" + hexColor + "\"></DIV>";
		 		
	 		return lineDiv;
	 	}
		
	    var iHtml=new Array();
	 	var yArray=new Array();
	 	
	 	///Pixel Height Width Start
		var dx=Math.abs(x1-x0);
	 	var dy=Math.abs(y1-y0);
	 	var pixHeight,pixWidth;
	 	var penWidth=parseInt(pen.width);
	 	
	 	pixHeight=Math.round(Math.sqrt((penWidth*penWidth)/((dy*dy)/(dx*dx)+1)));
	 	pixWidth=Math.round(Math.sqrt(penWidth*penWidth-pixHeight*pixHeight));
	
	 	if(pixWidth==0)
	 	{
	 		pixWidth=1;
	 	}
	 	if(pixHeight==0)
	 	{
	 		pixHeight=1;
	 	}
	 	///Pixel Height Width End

	 	var steep = Math.abs(y1 - y0) > Math.abs(x1 - x0); 
		if (steep)
		{   
			// swap   
			var tmp=x0;
			x0=y0;
			y0=tmp;
			tmp=x1;
			x1=y1;
			y1=tmp;
		}

		if (x0 > x1)
		{   
			// swap   
			var tmp=x0;
			x0=x1;
			x1=tmp;
			tmp=y0;
			y0=y1;
			y1=tmp;
		}
		
		var deltax = x1 - x0;
		var deltay = Math.abs(y1 - y0);
		var error  = deltax/2;
		var ystep;
		var y = y0;
		
		if (y0<y1) 
			ystep = 1; 
		else 
			ystep = -1;
			
		var xp,yp;
		var divWidth=0;
 		var divHeight=0;
 		if(steep)
 		{
 			divWidth=pixWidth;
 		}
 		else
 		{
 			divHeight=pixHeight;
 		}
		for (x=x0;x<=x1;x++)
		{
   			if (steep)
   			{ 
   				if(x==x0)
   				{
   					xp=y;
   					yp=x;
   				}
   				else
   				{
   					if(y==xp)
   					{
   						divHeight=divHeight+ 1;
   					}
   					else
   					{
   						divHeight=divHeight+pixHeight;
						iHtml[iHtml.length]="<DIV style=\"position:absolute;overflow:hidden;left:" + xp + "px;top:" + yp + "px;width:" + divWidth+ "px;height:" + 

divHeight + "px;background-color:" + hexColor + "\"></DIV>";
 						divHeight=0;		
 						xp=y;
	   					yp=x;		
 					}
 				}
 				
 				if(x==x1)
 				{
 					if(divHeight!=0)
 					{
 						divHeight=divHeight+pixHeight;
 						iHtml[iHtml.length]="<DIV style=\"position:absolute;overflow:hidden;left:" + xp + "px;top:" + yp + "px;width:" + divWidth+ "px;height:" + 

divHeight + "px;background-color:" + hexColor + "\"></DIV>";
 					}
 					else
 					{
 						divHeight=pixHeight;
						iHtml[iHtml.length]="<DIV style=\"position:absolute;overflow:hidden;left:" + y + "px;top:" + x + "px;width:" + divWidth+ "px;height:" + 

divHeight + "px;background-color:" + hexColor + "\"></DIV>";
 					}
 				}
 			}
			else
			{ 
				if(x==x0)
   				{
   					xp=x;
   					yp=y;
   				}
   				else
   				{
   					if(y==yp)
   					{
   						divWidth=divWidth + 1;
   					}
   					else
   					{
   						divWidth=divWidth+pixWidth;
						iHtml[iHtml.length]="<DIV style=\"position:absolute;overflow:hidden;left:" + xp + "px;top:" + yp + "px;width:" + divWidth+ "px;height:" + 

divHeight + "px;background-color:" + hexColor + "\"></DIV>";
	 					divWidth=0;
 						xp=x;
 						yp=y;			
 					}
 				}	
 				if(x==x1)
 				{
 					if(divWidth!=0)
 					{
   						divWidth=divWidth+pixWidth;
						iHtml[iHtml.length]="<DIV style=\"position:absolute;overflow:hidden;left:" + xp + "px;top:" + yp + "px;width:" + divWidth+ "px;height:" + 

divHeight + "px;background-color:" + hexColor + "\"></DIV>";
 					}
 					else
 					{
 						divWidth=pixWidth;
						iHtml[iHtml.length]="<DIV style=\"position:absolute;overflow:hidden;left:" + x + "px;top:" + y + "px;width:" + divWidth+ "px;height:" + 

divHeight + "px;background-color:" + hexColor + "\"></DIV>";
 					}
 				}
 			}

   			error = error - deltay;
   			if (error < 0)
			{     
				y = y + ystep;
     			error = error + deltax;
   			}
 		}
 		
 		lineDiv.innerHTML=iHtml.join("");
 		return lineDiv;
	}